//// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
//package com.linqingying.gitcode.pullrequest.ui.details.model.impl
//
//import com.intellij.collaboration.async.modelFlow
//import com.intellij.collaboration.ui.codereview.details.model.CodeReviewChangesContainer
//import com.intellij.collaboration.ui.codereview.details.model.CodeReviewChangesViewModel
//import com.intellij.collaboration.ui.codereview.details.model.CodeReviewChangesViewModelDelegate
//import com.intellij.collaboration.util.ComputedResult
//import com.intellij.collaboration.util.RefComparisonChange
//import com.intellij.openapi.diagnostic.thisLogger
//import com.intellij.openapi.project.Project
//import com.intellij.openapi.util.Disposer
//import com.intellij.platform.util.coroutines.childScope
//import git4idea.changes.GitBranchComparisonResult
//import kotlinx.coroutines.CoroutineScope
//import kotlinx.coroutines.Job
//import kotlinx.coroutines.channels.awaitClose
//import kotlinx.coroutines.flow.*
//import kotlinx.coroutines.future.asDeferred
//import kotlinx.coroutines.launch
//import org.jetbrains.annotations.ApiStatus
//import com.linqingying.gitcode.api.data.GCCommit
//import com.linqingying.gitcode.pullrequest.data.GCPRDataContext
//import com.linqingying.gitcode.pullrequest.data.provider.GCPRDataProvider
//import com.linqingying.gitcode.pullrequest.ui.GCApiLoadingErrorHandler
//import com.linqingying.gitcode.pullrequest.ui.details.model.GCPRChangeListViewModel
//import com.linqingying.gitcode.pullrequest.ui.details.model.GCPRChangeListViewModelImpl
//
//@ApiStatus.Experimental
//interface GCPRChangesViewModel : CodeReviewChangesViewModel<GCCommit> {
//  val changeListVm: StateFlow<ComputedResult<GCPRChangeListViewModel>>
//  val changesLoadingErrorHandler: GCApiLoadingErrorHandler
//
//  fun selectCommit(sha: String)
//  fun selectChange(change: RefComparisonChange)
//}
//
//internal class GCPRChangesViewModelImpl(
//  parentCs: CoroutineScope,
//  private val project: Project,
//  private val dataContext: GCPRDataContext,
//  private val dataProvider: GCPRDataProvider
//) : GCPRChangesViewModel {
//  private val cs = parentCs.childScope()
//
//  private val commitsResult: Flow<Result<List<GCCommit>>> = channelFlow {
//    val disp = Disposer.newDisposable()
//    var prev: Job? = null
//    dataProvider.changesData.loadCommitsFromApi(disp) {
//      prev?.cancel()
//      prev = launch {
//        val result = runCatching {
//          it.asDeferred().await()
//        }
//        send(result)
//      }
//    }
//    awaitClose { Disposer.dispose(disp) }
//  }
//
//  private val isUpdatingChanges = MutableStateFlow(false)
//  private val changesResult: Flow<Result<GitBranchComparisonResult>> = channelFlow {
//    val disp = Disposer.newDisposable()
//    var prev: Job? = null
//    dataProvider.changesData.loadChanges(disp) {
//      val isUpdate = prev != null
//      prev?.cancel()
//      prev = launch {
//        isUpdatingChanges.value = isUpdate
//        try {
//          val result = runCatching {
//            it.asDeferred().await()
//          }
//          send(result)
//        }
//        finally {
//          isUpdatingChanges.value = false
//        }
//      }
//    }
//    awaitClose { Disposer.dispose(disp) }
//  }
//
//  init {
//    // pre-fetch to show diff quicker
//    dataProvider.changesData.fetchBaseBranch()
//    dataProvider.changesData.fetchHeadBranch()
//  }
//
//  override val changesLoadingErrorHandler = GCApiLoadingErrorHandler(project, dataContext.securityService.account) {
//    dataProvider.changesData.reloadChanges()
//  }
//
//  override val reviewCommits: StateFlow<List<GCCommit>> = commitsResult
//    .map { it.getOrNull() ?: listOf() }
//    .stateIn(cs, SharingStarted.Eagerly, listOf())
//
//  private val changesContainer: Flow<Result<CodeReviewChangesContainer>> = changesResult.map { changesResult ->
//    changesResult.map {
//      CodeReviewChangesContainer(it.changes, it.commits.map { it.sha }, it.changesByCommits)
//    }
//  }
//
//  private val delegate = CodeReviewChangesViewModelDelegate(cs, changesContainer) { changes, changeList ->
//    GCPRChangeListViewModelImpl(this, project, dataContext, dataProvider, changes, changeList).also { vm ->
//      launch {
//        isUpdatingChanges.collect {
//          vm.setUpdating(it)
//        }
//      }
//    }
//  }
//
//  override val selectedCommitIndex: SharedFlow<Int> = reviewCommits.combine(delegate.selectedCommit) { commits, sha ->
//    if (sha == null) -1
//    else commits.indexOfFirst { it.oid.startsWith(sha) }
//  }.modelFlow(cs, thisLogger())
//
//  override val selectedCommit: SharedFlow<GCCommit?> = reviewCommits.combine(selectedCommitIndex) { commits, index ->
//    index.takeIf { it >= 0 }?.let { commits[it] }
//  }.modelFlow(cs, thisLogger())
//
//  override val changeListVm: StateFlow<ComputedResult<GCPRChangeListViewModelImpl>> = delegate.changeListVm
//
//  override fun selectCommit(index: Int) {
//    delegate.selectCommit(index)
//  }
//
//  override fun selectNextCommit() {
//    delegate.selectNextCommit()
//  }
//
//  override fun selectPreviousCommit() {
//    delegate.selectPreviousCommit()
//  }
//
//  override fun selectCommit(sha: String) {
//    delegate.selectCommit(sha)
//  }
//
//  override fun selectChange(change: RefComparisonChange) {
//    delegate.selectChange(change)
//  }
//
//  override fun commitHash(commit: GCCommit): String = commit.abbreviatedOid
//}
